package restc

import (
	"strconv"
	"net/http"
	"net/url"
	"encoding/json"
	"io/ioutil"
	"reflect"
	"fmt"
	"bytes"
	"log"
)

func FormEncode(params interface{}) (str string) {

	t := reflect.TypeOf(params)
	v := reflect.ValueOf(params)

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)

		name := string(field.Tag)

		if name == "" {
			name = field.Name
		}

		value := v.Field(i).String()

		switch v.Field(i).Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			value = strconv.FormatInt(v.Field(i).Int(), 10)
		case reflect.Bool:
			if v.Field(i).Bool() == false {
				value = "false"
			} else {
				value = "true"
			}
		}

		if value != "" {
			str += fmt.Sprintf("&%s=%s", url.QueryEscape(name), url.QueryEscape(value))
		}
	}

	return
}

func Url(base string, parts ...string) (str string) {

	str = base

	for _, part := range parts {
		str += "/" + url.QueryEscape(part)
	}
	
	return
}

func Get(urlstr string, params interface{}, obj interface{}) error {

	if params != nil {
		urlstr += "?" + FormEncode(params)
	}

	resp, err := http.Get(urlstr)

	if err != nil {
		return err
	}

	text, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return err
	}

	if resp.StatusCode != 200 {
		log.Println(urlstr, " -> ", resp.StatusCode)
	}
	
	defer resp.Body.Close()

	err = json.Unmarshal(text, obj)

	if err != nil {
		log.Println(err, "\n", string(text))
	}

	return err
}

func Post(urlstr string, params interface{}, obj interface{}) error {

	buf, err := json.Marshal(obj)

	if err != nil {
		log.Println(err)
		return err
	}

	if params != nil {
		urlstr += FormEncode(params)
	}

	resp, err := http.Post(urlstr, "text/json", bytes.NewBuffer(buf))

	if err != nil {
		log.Println(err)
		return err
	}

	if resp.StatusCode != 200 {
		log.Println(urlstr, " -> ", resp.StatusCode)
	}

	defer resp.Body.Close()

	return nil
}

func PostText(urlstr string, params interface{}, text string) error {

	if params != nil {
		urlstr += FormEncode(params)
	}

	resp, err := http.Post(urlstr, "text/plain", bytes.NewBufferString(text))

	if err != nil {
		log.Println(err)
		return err
	}

	if resp.StatusCode != 200 {
		log.Println(urlstr, " -> ", resp.StatusCode)
	}
	
	defer resp.Body.Close()

	return nil
}


func Put(urlstr string, params interface{}, obj interface{}) error {

	buf, err := json.Marshal(obj)

	if err != nil {
		return err
	}

	if params != nil {
		urlstr += FormEncode(params)
	}

	req, err := http.NewRequest("PUT", urlstr, bytes.NewBuffer(buf))

	if err != nil {
		log.Println(err)
		return err
	}

	req.Header.Set("Content-type", "text/json")

	resp, err := http.DefaultClient.Do(req)

	if err != nil {
		log.Println(err)
		return err
	}
	
	defer resp.Body.Close()

	return nil
}
